package com.sc.nft.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.admin.request.*;
import com.sc.nft.admin.vo.DepartmentWalletApprovalVO;
import com.sc.nft.admin.vo.DepartmentWalletInDetailVO;
import com.sc.nft.admin.vo.DepartmentWalletOutDetailVO;
import com.sc.nft.admin.vo.DepartmentWalletVO;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.SecondOrderExportListVO;
import com.sc.nft.entity.vo.SecondOrderExportVO;
import com.sc.nft.enums.ConSignStatus;
import com.sc.nft.enums.DigitalMarketTypeEnum;
import com.sc.nft.enums.MarketTypeEnum;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.enums.wallet.DepartmentDetailTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.SysMemberPool;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.io.File;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/departmentWallet")
@Api(tags = "部门钱包管理")
public class DepartmentAdminController {
    private final DepartmentWalletService departmentWalletService;
    private final UserInfoDao userInfoDao;
    private final IdcardInfoDao idcardInfoDao;
    private final SysMemberDao sysMemberDao;
    private final Redisson redisson;

    @PostMapping(value = "/page", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "部门钱包列表", notes = "部门钱包列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<DepartmentWalletVO> page(@Valid @RequestBody PageRequest pageRequest) {
        Page<DepartmentWallet> page = departmentWalletService.page(pageRequest.toMp());
        Page<DepartmentWalletVO> result = new Page(page.getCurrent(),page.getSize(),page.getTotal());
        List<DepartmentWalletVO> records = Lists.newArrayList();
        for (DepartmentWallet record : page.getRecords()) {
            DepartmentWalletVO departmentWalletVO = new DepartmentWalletVO();
            departmentWalletVO.setDepartmentName(record.getDepartmentType().getDescription());
            departmentWalletVO.setSumIncome(record.getSumIncome());
            departmentWalletVO.setBalance(record.getBalance());
            departmentWalletVO.setFreezeAmount(record.getFreezeAmount());
            records.add(departmentWalletVO);
        }
        result.setRecords(records);
        return PageResult.success(result);
    }

    @PostMapping(value = "/inRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "钱包入账明细记录", notes = "钱包入账明细记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<DepartmentWalletInDetailVO> inRecord(@Valid @RequestBody DepartmentDetailRequest request) {
        Long userId =null;
        if(StrUtil.isNotBlank(request.getUserTel())){
            UserInfo userInfo = userInfoDao.getOneByUserTel(request.getUserTel());
            userId = userInfo!=null?userInfo.getId():0L;
        }

        Page<DepartmentWalletDetail> page = departmentWalletService.record(request.getDepartmentType(), userId,DepartmentDetailTypeEnum.ADD,request.getMarketLevel(),null,request.getOrderNo(),request.getStartTime(),request.getEndTime(), request.toMp());
        Page<DepartmentWalletInDetailVO> result = new Page(page.getCurrent(),page.getSize(),page.getTotal());
        List<DepartmentWalletInDetailVO> records = Lists.newArrayList();
        for (DepartmentWalletDetail record : page.getRecords()) {
            DepartmentWalletInDetailVO inDetailVO = new DepartmentWalletInDetailVO();
            inDetailVO.setOrderNo(record.getOrderNo());
            inDetailVO.setMarketLevel(record.getMarketLevel());
            inDetailVO.setMarketLevelTxt(inDetailVO.getMarketLevel().getDescription());
            inDetailVO.setAmount(record.getAmount());
            inDetailVO.setCreateTime(record.getCreateTime());
            records.add(inDetailVO);
        }
        result.setRecords(records);
        return PageResult.success(result);
    }


    @PostMapping(value = "/outRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "钱包出账明细记录", notes = "钱包出账明细记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<DepartmentWalletOutDetailVO> outRecord(@Valid @RequestBody DepartmentDetailRequest request) {
        Page<DepartmentWalletDetail> page = departmentWalletService.record(request.getDepartmentType(),null,DepartmentDetailTypeEnum.TRANSFER,request.getMarketLevel(),null,request.getOrderNo(),request.getStartTime(),request.getEndTime(), request.toMp());
        Page<DepartmentWalletOutDetailVO> result = new Page(page.getCurrent(),page.getSize(),page.getTotal());
        List<DepartmentWalletOutDetailVO> records = Lists.newArrayList();
        for (DepartmentWalletDetail record : page.getRecords()) {
            DepartmentWalletOutDetailVO outDetailVO = new DepartmentWalletOutDetailVO();
            outDetailVO.setId(record.getId());
            outDetailVO.setAmount(record.getAmount());
            outDetailVO.setUserTel(userInfoDao.getUserTelById(record.getUserId()));
            outDetailVO.setName(idcardInfoDao.getByUserIdAndIsPass(record.getUserId()).getName());
            outDetailVO.setCreateTime(record.getCreateTime());
            outDetailVO.setApplyRemark(record.getApplyRemark());
            outDetailVO.setApprovalRemark(record.getApprovalRemark());
            outDetailVO.setStatus(record.getStatus());
            records.add(outDetailVO);
        }
        result.setRecords(records);
        return PageResult.success(result);
    }


    @PostMapping(value = "/approvalRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "审核列表", notes = "审核列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<DepartmentWalletApprovalVO> approvalRecord(@Valid @RequestBody DepartmentApprovalPageRequest request) {
        Page<DepartmentWalletDetail> page = departmentWalletService.record(request.getDepartmentType(),null,DepartmentDetailTypeEnum.TRANSFER,null, request.getStatus(),null,null,null, request.toMp());
        Page<DepartmentWalletApprovalVO> result = new Page(page.getCurrent(),page.getSize(),page.getTotal());
        List<DepartmentWalletApprovalVO> records = Lists.newArrayList();
        for (DepartmentWalletDetail record : page.getRecords()) {
            DepartmentWalletApprovalVO vo = new DepartmentWalletApprovalVO();
            vo.setId(record.getId());
            vo.setDepartmentType(record.getDepartmentType());
            vo.setDepartmentName(record.getDepartmentType().getDescription());
            vo.setAmount(record.getAmount());
            vo.setUserTel(userInfoDao.getUserTelById(record.getUserId()));
            vo.setName(idcardInfoDao.getByUserIdAndIsPass(record.getUserId()).getName());
            vo.setCreateTime(record.getCreateTime());
            vo.setApplyRemark(record.getApplyRemark());
            vo.setApprovalRemark(record.getApprovalRemark());
            vo.setApplyUser(sysMemberDao.getById(record.getApplyId()).getUserName());
            vo.setStatus(record.getStatus());
            records.add(vo);
        }
        result.setRecords(records);
        return PageResult.success(result);
    }

    @PostMapping(value = "/allocation", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "奖金分配", notes = "奖金分配", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result allocation(@Valid @RequestBody DepartmentAllocationRequest request) {
        RLock lock = redisson.getLock(StrUtil.format("DEPARTMENT_ALLOCATION:{}",request.getUserTel()) );
        try {
            boolean res = lock.tryLock(3, TimeUnit.SECONDS);
            if (res) {
                departmentWalletService.transfer(request.getDepartmentType(), SysMemberPool.getMember(),request.getUserTel(),request.getAmount(),request.getApplyRemark());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("请勿重复提交");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @PostMapping(value = "/revoke", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "撤销", notes = "撤销", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result revoke(@Valid @RequestBody IdRequest request) {
        RLock lock = redisson.getLock(StrUtil.format("DEPARTMENT_REVOKE:{}",request.getId()) );
        try {
            boolean res = lock.tryLock(3, TimeUnit.SECONDS);
            if (res) {
                departmentWalletService.revoke(request.getId(),SysMemberPool.getMember());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("请勿重复提交");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @PostMapping(value = "/approval", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "审批", notes = "审批", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result approval(@Valid @RequestBody DepartmentApprovalRequest request) {
        RLock lock = redisson.getLock(StrUtil.format("DEPARTMENT_APPROVAL:{}",request.getId()) );
        try {
            boolean res = lock.tryLock(3, TimeUnit.SECONDS);
            if (res) {
                departmentWalletService.approval(request.getId(),request.getStatus(),request.getApprovalRemark(),SysMemberPool.getMember());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("请勿重复提交");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }


    @PostMapping(value = "/batchApproval", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "批量审批", notes = "批量审批", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result batchApproval(@Valid @RequestBody DepartmentBatchApprovalRequest request) {
        for (Long id : request.getIds()) {
            RLock lock = redisson.getLock(StrUtil.format("DEPARTMENT_APPROVAL:{}",id) );
            try {
                boolean res = lock.tryLock(3, TimeUnit.SECONDS);
                if (res) {
                    departmentWalletService.approval(id,request.getStatus(),request.getApprovalRemark(),SysMemberPool.getMember());
                }else {
                    return Result.fail(ErrorCode.LATER_TRY);
                }
            } catch (InterruptedException e) {
                return Result.fail("请勿重复提交");
            } finally {
                lock.unlock();
            }
        }

        return Result.success();
    }


    private  final UserCollectionDao userCollectionDao;
    private  final UserCollectionService userCollectionService;
    @PostMapping(value = "/test1", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "test1", notes = "test1", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result test1( ) {
        List<UserCollection> list = userCollectionDao.getOneByGiveStatus();
        for (UserCollection userCollection : list) {
            userCollectionService.editGiveStatus(userCollection);
        }
        return Result.success();
    }


}
